home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 22
/
Aminet 22 (1997)(GTI - Schatztruhe)[!][Dec 1997].iso
/
Aminet
/
util
/
blank
/
BeyondTheDark.lha
/
BeyondTheDark
/
Developer
/
Source
/
Toaster
/
Toaster.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-04-20
|
15KB
|
572 lines
#include <exec/memory.h>
#include <exec/execbase.h>
#include <graphics/gfxbase.h>
#include <intuition/intuitionbase.h>
#include <libraries/iffparse.h>
#include <utility/tagitem.h>
#include <cybergraphics/cybergraphics.h>
#define __USE_SYSBASE 42
#include <proto/cybergraphics.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/utility.h>
#include <string.h>
#include "btd.h"
struct GfxBase *GfxBase;
struct IntuitionBase *IntuitionBase;
struct Library *UtilityBase,*CyberGfxBase;
#define TPTAG(o) (BTD_Client+(o))
#define TP_Toasters TPTAG(0)
#define MAX_TOASTERS 20L
#define DEF_TOASTERS 2L
#define NUM_IMAGES 4
#define IMAGE_WIDTH 64
#define IMAGE_HEIGHT 64
#define IMAGE_WIDBUF (IMAGE_WIDTH+20)
#define IMAGE_HEIBUF (IMAGE_HEIGHT+20)
extern UBYTE *BytePackedFrames[];
#define ABS(x) __builtin_abs(x)
#define MIN(a,b) __builtin_min(a,b)
#define MAX(a,b) __builtin_max(a,b)
#define NUM_COLORS 16
#define NUM_PHASES ((NUM_IMAGES*2)-2)
struct BTDInteger ToasterIntParams[] =
{
TP_Toasters,"Toasters",BTDPT_INTEGER,DEF_TOASTERS,1L,MAX_TOASTERS,TRUE,
};
struct BTDNode *ToasterParams[] =
{
&ToasterIntParams[0].BI_Node,
NULL
};
struct BTDInfo ToasterInfo =
{
BTDI_Revision,MAKE_ID('T','O','S','T'),
"Toaster","The Must of Blankers","Markus Illenseer and Matthias Scheler",
ToasterParams
};
struct IToaster
{
LONG delay;
LONG x, y;
LONG old_x,old_y;
LONG xspeed,yspeed;
LONG phase;
LONG xcol,ycol;
};
struct Toasters /* structure for a swarm, including the wasp */
{
struct BTDDrawInfo *BTDDrawInfo;
WORD Width; /* Width and */
WORD Height; /* Height of the used area */
WORD NumToaster; /* total number of the Toasters*/
struct IToaster *Toasters;
struct ToasterImage *Images[NUM_PHASES];
LONG RandN,RandF,RandI;
};
UBYTE CMap[(NUM_COLORS-1)*3] =
{
0x33,0x33,0x33,0x55,0x55,0x55,0x88,0x55,0x22,0x66,0x66,0x66,0x77,0x77,0x44,
0x55,0x55,0x66,0xEE,0x55,0x22,0x88,0x88,0x88,0x99,0x99,0x99,0xBB,0xBB,0xBB,
0xCC,0xCC,0xCC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0xEE,0xEE,0xFF,0xFF,0xFF
};
struct ToasterImage
{
WORD ti_Width,ti_Height;
struct BitMap ti_BitMap;
UBYTE *ti_ChunkyData;
};
/* library stuff */
char MyBlankerName[] = "toaster.btd";
char MyBlankerID[] = "Toaster Blanker V" VERSION "." REVISION " for BTD";
LONG MyBlankerLibInit(void)
{
if (GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37L))
{
if (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37L))
{
if (UtilityBase=OpenLibrary("utility.library",37L))
{
CyberGfxBase=OpenLibrary("cybergraphics.library",40L);
return TRUE;
}
CloseLibrary (&IntuitionBase->LibNode);
}
CloseLibrary (&GfxBase->LibNode);
}
return FALSE;
}
void MyBlankerLibFree(void)
{
if (CyberGfxBase) CloseLibrary (CyberGfxBase);
CloseLibrary (UtilityBase);
CloseLibrary (&IntuitionBase->LibNode);
CloseLibrary (&GfxBase->LibNode);
}
/* random generator */
void __regargs InitRandom(struct Toasters *TP,ULONG Instance)
{
ULONG Time[2];
CurrentTime (&Time[0],&Time[1]);
TP->RandN=(LONG)Time[0];
if (Time[1]<1024L) Time[1]|=1;
else Time[1]>>=10;
Time[1]^=Instance;
TP->RandF=4*Time[1]+1;
TP->RandI=2*Time[1]+1;
}
WORD __regargs Random(struct Toasters *TP,WORD Max)
{
TP->RandN=TP->RandF*TP->RandN+TP->RandI;
if (TP->RandN<0L) TP->RandN=-TP->RandN;
return (WORD)(TP->RandN%Max);
}
/* implementation of library functions */
struct BTDInfo *QueryMyBlanker(void)
{
return &ToasterInfo;
}
void __regargs DeleteToasterImage(struct ToasterImage *TI)
{
if (TI->ti_ChunkyData) FreeVec (TI->ti_ChunkyData);
else
{
ULONG Index,Size;
Size=TI->ti_BitMap.BytesPerRow*TI->ti_BitMap.Rows;
for (Index=0L; Index<TI->ti_BitMap.Depth; Index++)
FreeMem (TI->ti_BitMap.Planes[Index],Size);
}
FreeVec (TI);
}
struct ToasterImage __regargs *ConvertToasterImage(UBYTE *From,UWORD *RemapTab,
struct RastPort *RastPort,LONG Chunky)
{
struct ToasterImage *Target;
if ((Target=AllocVec(sizeof(struct ToasterImage),MEMF_PUBLIC))==NULL) return NULL;
Target->ti_Width=IMAGE_WIDTH;
Target->ti_Height=IMAGE_HEIGHT;
if (Chunky)
{
ULONG Pixels;
Pixels=Target->ti_Width*Target->ti_Height;
if (Target->ti_ChunkyData=AllocVec(Pixels,MEMF_PUBLIC))
{
UBYTE *To,Nibble;
To=Target->ti_ChunkyData;
while (Pixels)
{
Nibble=*From>>4;
if (Nibble) *To++=RemapTab[Nibble];
else *To++=BTD_BgPen;
Nibble=(*From++)&15;
if (Nibble) *To++=RemapTab[Nibble];
else *To++=BTD_BgPen;
Pixels-=2L;
}
}
else
{
FreeVec (Target);
Target=NULL;
}
}
else
{
ULONG Index,Size;
LONG Depth,X,Y;
Target->ti_ChunkyData=NULL;
Depth=1L;
for (Index=1L; Index<NUM_COLORS; Index++)
while (RemapTab[Index]>=(1L<<Depth)) Depth++;
InitBitMap (&Target->ti_BitMap,Depth,Target->ti_Width,Target->ti_Height);
Size=Target->ti_BitMap.BytesPerRow*Target->ti_BitMap.Rows;
for (Index=0L; Index<Target->ti_BitMap.Depth; Index++)
if ((Target->ti_BitMap.Planes[Index]=AllocMem(Size,MEMF_CHIP|MEMF_CLEAR))==NULL)
{
while (Index--) FreeMem (Target->ti_BitMap.Planes[Index],Size);
FreeVec (Target);
return NULL;
}
RastPort->BitMap=&Target->ti_BitMap;
if (GfxBase->LibNode.lib_Version>=40)
{
ULONG Pixels;
UBYTE *Data;
Pixels=Target->ti_Width*Target->ti_Height;
if (Data=AllocVec(Pixels,MEMF_PUBLIC))
{
UBYTE *To,Nibble;
To=Data;
while (Pixels)
{
Nibble=*From>>4;
if (Nibble) *To++=RemapTab[Nibble];
else *To++=BTD_BgPen;
Nibble=(*From++)&15;
if (Nibble) *To++=RemapTab[Nibble];
else *To++=BTD_BgPen;
Pixels-=2L;
}
WriteChunkyPixels (RastPort,0,0,Target->ti_Width-1,Target->ti_Height-1,Data,IMAGE_WIDTH);
FreeVec (Data);
return Target;
}
}
for (Y=0L; Y<Target->ti_Height; Y++)
for (X=0L; X<Target->ti_Width; X+=2)
{
UBYTE Nibble;
Nibble=*From>>4;
if (Nibble)
{ SetAPen (RastPort,RemapTab[Nibble]);
(void)WritePixel(RastPort,X,Y);
}
Nibble=(*From++)&15;
if (Nibble)
{ SetAPen (RastPort,RemapTab[Nibble]);
(void)WritePixel(RastPort,X+1,Y);
}
}
}
return Target;
}
void __regargs SafeEraseRect(struct BTDDrawInfo *BTDDrawInfo,
LONG Left,LONG Top,
LONG Right,LONG Bottom)
{
if ((Left<BTDDrawInfo->BDI_Width)&&(Right>=MAX(Left,0L))&&
(Top<BTDDrawInfo->BDI_Height)&&(Bottom>=MAX(Top,0L)))
EraseRect (BTDDrawInfo->BDI_RPort,
BTDDrawInfo->BDI_Left+MAX(Left,0L),
BTDDrawInfo->BDI_Top+MAX(Top,0L),
BTDDrawInfo->BDI_Left+MIN(Right,BTDDrawInfo->BDI_Width-1),
BTDDrawInfo->BDI_Top+MIN(Bottom,BTDDrawInfo->BDI_Height-1));
}
void __regargs DrawToasterImage(struct BTDDrawInfo *BTDDrawInfo,
struct ToasterImage *TI,
LONG XPos,LONG YPos)
{
LONG Left,Top,Right,Bottom;
Left=MAX(XPos,0L);
Top=MAX(YPos,0L);
Right=MIN(XPos+TI->ti_Width,BTDDrawInfo->BDI_Width);
Bottom=MIN(YPos+TI->ti_Height,BTDDrawInfo->BDI_Height);
if ((Left<Right)&&(Top<Bottom))
if (TI->ti_ChunkyData)
(void)WritePixelArray(TI->ti_ChunkyData,Left-XPos,Top-YPos,TI->ti_Width,
BTDDrawInfo->BDI_RPort,Left,Top,
Right-Left,Bottom-Top,RECTFMT_LUT8);
else
BltBitMapRastPort (&TI->ti_BitMap,Left-XPos,Top-YPos,
BTDDrawInfo->BDI_RPort,Left,Top,
Right-Left,Bottom-Top,0xC0);
}
LONG __regargs TestExtent(struct Toasters *TP,LONG Start,LONG Me,LONG x,LONG y)
{
LONG Index;
for (Index=Start; Index<TP->NumToaster; Index++)
if ((Index!=Me)&&!TP->Toasters[Index].delay&&
(ABS(x-TP->Toasters[Index].x)<IMAGE_WIDBUF)&&
(ABS(y-TP->Toasters[Index].y)<IMAGE_HEIBUF)) return Index;
return -1L;
}
BOOL __regargs FindLaunchPos(struct Toasters *TP,LONG Index)
{
LONG x,y;
x=TP->Width-IMAGE_WIDTH;
y=IMAGE_HEIGHT+Random(TP,TP->Height);
FOREVER
{
if (x<=(2*IMAGE_WIDTH)) return FALSE;
if (TestExtent(TP,0,Index,x,y)==-1L)
{
TP->Toasters[Index].x=TP->Toasters[Index].old_x=x;
TP->Toasters[Index].y=TP->Toasters[Index].old_y=y;
TP->Toasters[Index].xspeed=Random(TP,3)+1;
TP->Toasters[Index].yspeed=Random(TP,2)+1;
TP->Toasters[Index].phase=Random(TP,NUM_IMAGES);
return TRUE;
}
if (y>(-IMAGE_HEIGHT)) y-=IMAGE_HEIGHT;
else x-=IMAGE_WIDTH;
}
}
LONG __regargs ActXSpeed(struct Toasters *TP,LONG Index)
{
if (TP->Toasters[Index].xcol==-1L) return TP->Toasters[Index].xspeed;
else return ActXSpeed(TP,TP->Toasters[Index].xcol);
}
LONG __regargs ActYSpeed(struct Toasters *TP,LONG Index)
{
if (TP->Toasters[Index].ycol==-1L) return TP->Toasters[Index].yspeed;
else return ActXSpeed(TP,TP->Toasters[Index].ycol);
}
void EndMyBlanker(struct Toasters *TP)
{
ULONG Index;
for (Index=0L; Index<NUM_IMAGES; Index++)
if (TP->Images[Index]) DeleteToasterImage (TP->Images[Index]);
FreeVec (TP);
}
struct Toasters *InitMyBlanker(struct TagItem *TagList)
{
struct BTDDrawInfo *BTDDrawInfo;
ULONG *Error,Dummy,Instance,Index;
LONG Chunky,NumToaster;
struct Toasters *TP;
struct RastPort TempRastPort;
UBYTE *CMapPtr;
if ((BTDDrawInfo=(struct BTDDrawInfo *)
GetTagData(BTD_DrawInfo,NULL,TagList))==NULL) return NULL;
Error=(ULONG *)GetTagData(BTD_Error,(ULONG)&Dummy,TagList);
Chunky=(CyberGfxBase==NULL)?FALSE:GetCyberMapAttr(BTDDrawInfo->BDI_RPort->BitMap,CYBRMATTR_ISCYBERGFX);
Instance=GetTagData(BTD_Instance,0L,TagList);
NumToaster=GetTagData(TP_Toasters,DEF_TOASTERS,TagList);
if ((TP=AllocVec(sizeof(struct Toasters)+sizeof(struct IToaster)*NumToaster,MEMF_PUBLIC|MEMF_CLEAR))==NULL)
{
*Error=BTDERR_Memory;
return NULL;
}
TP->Toasters=(struct IToaster *)&TP[1];
InitRastPort (&TempRastPort);
for (Index=0L; Index<NUM_IMAGES; Index++)
if ((TP->Images[Index]=ConvertToasterImage(BytePackedFrames[Index],
BTDDrawInfo->BDI_Pens-1,
&TempRastPort,Chunky))==NULL)
{
EndMyBlanker (TP);
*Error=BTDERR_Memory;
return NULL;
}
for (; Index<NUM_PHASES; Index++)
TP->Images[Index]=TP->Images[NUM_PHASES-Index];
TP->BTDDrawInfo=BTDDrawInfo;
TP->Width=BTDDrawInfo->BDI_Width;
TP->Height=BTDDrawInfo->BDI_Height;
TP->NumToaster=NumToaster;
InitRandom (TP,Instance);
for (Index=0L, CMapPtr=CMap; Index<(NUM_COLORS-1L); Index++)
{
BTDDrawInfo->BDI_Red[BTDDrawInfo->BDI_Pens[Index]]=*CMapPtr++;
BTDDrawInfo->BDI_Green[BTDDrawInfo->BDI_Pens[Index]]=*CMapPtr++;
BTDDrawInfo->BDI_Blue[BTDDrawInfo->BDI_Pens[Index]]=*CMapPtr++;
BTDDrawInfo->BDI_Changed[BTDDrawInfo->BDI_Pens[Index]]=TRUE;
}
for (Index=0L; Index<NumToaster; Index++)
if (!FindLaunchPos(TP,Index)) TP->Toasters[Index].delay=30;
return TP;
}
void AnimMyBlanker(struct Toasters *TP)
{
struct BTDDrawInfo *BTDDrawInfo;
LONG i,j;
BTDDrawInfo=TP->BTDDrawInfo;
for (i=0; i<TP->NumToaster; i++)
if (TP->Toasters[i].delay==0L)
{
TP->Toasters[i].old_x=TP->Toasters[i].x;
TP->Toasters[i].old_y=TP->Toasters[i].y;
TP->Toasters[i].x-=TP->Toasters[i].xspeed;
TP->Toasters[i].y+=TP->Toasters[i].yspeed;
TP->Toasters[i].xcol=-1;
TP->Toasters[i].ycol=-1;
}
for (i=0; i<TP->NumToaster; i++)
{
if (TP->Toasters[i].delay==0L)
{
j=-1;
while ((j=TestExtent(TP,j+1,i,TP->Toasters[i].x,TP->Toasters[i].y))>=0)
{
if (ABS(TP->Toasters[j].old_x-TP->Toasters[i].old_x)<(IMAGE_WIDBUF))
{
if (TP->Toasters[i].y<TP->Toasters[j].y) TP->Toasters[i].ycol=j;
if (TP->Toasters[i].xspeed==TP->Toasters[j].xspeed) TP->Toasters[i].xspeed++;
}
else
{
if (TP->Toasters[i].x > TP->Toasters[j].x) TP->Toasters[i].xcol=j;
if (TP->Toasters[i].yspeed==TP->Toasters[j].yspeed) TP->Toasters[i].yspeed++;
}
if (ABS(TP->Toasters[j].old_y-TP->Toasters[i].old_y)<(IMAGE_HEIBUF))
{
if (TP->Toasters[i].x > TP->Toasters[j].x) TP->Toasters[i].xcol=j;
if (TP->Toasters[i].yspeed==TP->Toasters[j].yspeed) TP->Toasters[i].yspeed++;
}
}
}
}
for (i=0; i<TP->NumToaster; i++)
{
if (TP->Toasters[i].delay==0L)
{
TP->Toasters[i].x=TP->Toasters[i].old_x-ActXSpeed(TP,i);
TP->Toasters[i].y=TP->Toasters[i].old_y + ActYSpeed(TP,i);
}
}
for (i=0; i<TP->NumToaster; i++)
{
if (TP->Toasters[i].delay==0L)
{
j=-1;
while ((j=TestExtent(TP,j+1,i,TP->Toasters[i].x,TP->Toasters[i].y))>=0)
{
if (ABS(TP->Toasters[j].old_x-TP->Toasters[i].old_x)<(IMAGE_WIDBUF))
if (TP->Toasters[i].x > TP->Toasters[j].x) TP->Toasters[i].x=TP->Toasters[i].old_x;
else
if (TP->Toasters[i].y<TP->Toasters[j].y) TP->Toasters[i].y=TP->Toasters[i].old_y;
if (ABS(TP->Toasters[j].old_y-TP->Toasters[i].old_y)<(IMAGE_HEIBUF))
if (TP->Toasters[i].y<TP->Toasters[j].y)
TP->Toasters[i].y=TP->Toasters[i].old_y;
}
}
}
for (i=0; i<TP->NumToaster; i++)
if (TP->Toasters[i].delay==0L)
{
TP->Toasters[i].phase=(TP->Toasters[i].phase+1)%NUM_PHASES;
SafeEraseRect (BTDDrawInfo,
TP->Toasters[i].x+IMAGE_WIDTH,
TP->Toasters[i].old_y,
TP->Toasters[i].x+IMAGE_WIDTH+TP->Toasters[i].xspeed,
TP->Toasters[i].old_y+IMAGE_HEIGHT);
SafeEraseRect (BTDDrawInfo,
TP->Toasters[i].old_x,
TP->Toasters[i].old_y,
TP->Toasters[i].old_x+IMAGE_WIDTH,
TP->Toasters[i].old_y+TP->Toasters[i].yspeed);
DrawToasterImage (BTDDrawInfo,TP->Images[TP->Toasters[i].phase],
TP->Toasters[i].x,TP->Toasters[i].y);
if ((TP->Toasters[i].x<=(-IMAGE_WIDTH-1))||
(TP->Toasters[i].y>=TP->Height)) TP->Toasters[i].delay=Random(TP,50);
}
else
if (--TP->Toasters[i].delay==0L)
TP->Toasters[i].delay=FindLaunchPos(TP,i)?0:30;
WaitTOF();
}
ULONG PenCountMyBlanker(struct TagItem *TagList)
{
return NUM_COLORS-1L;
}